package org.youyee.game.displayArea
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import org.youyee.game.event.MapObjectEvent;
	import org.youyee.game.managers.DepthManager;
	import org.youyee.game.managers.MapObjectManager;
	import org.youyee.game.object.MapObject;
	import org.youyee.game.pathFinding.PathMap;
	import org.youyee.game.utils.FloorGenerator;
	import org.youyee.game.utils.MapGraphicUtil;
	import org.youyee.game.utils.PositionCalculator;

	/**
	 * 在游戏场景中的一个区域对象 
	 * @author youyee
	 * 
	 */	
	public class Area extends Sprite
	{
		protected static var _areaIndex:int = 0;
		
		protected var _pathMap:PathMap;
		protected var _id:int;
		protected var _nodeX:int;
		protected var _nodeY:int;
		
		//容器层
		public var objectLayer:Sprite;							/*放置普通场景上的物品*/
		public var floorLayer:Sprite;							/*地板层*/
		public var bitmapCacheLayer:Sprite;						/*地板位图缓存层*/
		public var floorItemLayer:Sprite;						/*地板上的物品，如垃圾放置到此层*/
		public var backgroundLayer:Sprite;						/*背景物品层，除了地板外的所有场景物品放置在此层，比如：墙*/
		public var tipsLayer:Sprite;							/*提示层，这里放置物品的Tips，物品操作的组合按钮等等*/
		public var ruler:Sprite;								/*一个用于负责位置转换的尺子*/
		public var mode:int;									/*显示的模式*/
		
		//管理器
		protected var _depthManager:DepthManager;				/*深度管理器*/
		protected var _mapObjectManager:MapObjectManager;		/*场景上物品的管理器*/
		
		//地板位图缓存相关对象
		protected var _floorBitmap:Bitmap;
		protected var _floorUseCache:Boolean;
		
		/**
		 * 构造函数 
		 * @param nodeX 区域在世界地图中的横轴位置
		 * @param nodeY 区域在世界地图中的纵轴位置
		 * @param width 区域的宽度
		 * @param height 区域的高度
		 * @param pathNodeHeight 每个格子的宽度
		 * @param pathNodeWidth 每个格子的高度
		 * @param displayMode 显示模式
		 * @param areaId 区域的ID
		 * 
		 */		
		public function Area(nodeX:int, nodeY:int, width:int=10, height:int=10, pathNodeWidth:Number=70, pathNodeHeight:Number=35, displayMode:int=0, areaId:int=-1)
		{
			this._id = areaId < 0 ? _areaIndex++ : areaId;
			this._pathMap = new PathMap(width, height);
			
			this._nodeX = nodeX;
			this._nodeY = nodeY;
			
			PositionCalculator.WIDTH_VALUE = MapGraphicUtil.WIDTH_VALUE = pathNodeWidth / 2;
			PositionCalculator.HEIGHT_VALUE = MapGraphicUtil.HEIGHT_VALUE = pathNodeHeight / 2;
			this.mode = PositionCalculator.MODE = displayMode;
			
			var p:Point = PositionCalculator.getPosition(nodeX, nodeY);
			
			this.x = p.x;
			this.y = p.y;
			
			_floorUseCache = false;
			generateLayer();
			initManager();
			initListener();
			
			drawMeasureObject();
		}
		
		protected function drawMeasureObject():void
		{
			ruler = new Sprite();
			ruler.graphics.beginFill(0);
			ruler.graphics.drawRect(0, 0, 10, 10);
			ruler.graphics.endFill();
			ruler.rotation = 45;
			
			var c:Sprite = new Sprite();
			c.addChild(ruler);
			c.width = PositionCalculator.WIDTH_VALUE * 2;
			c.height = PositionCalculator.HEIGHT_VALUE * 2;
			
			c.mouseChildren = c.mouseEnabled = false;
			c.visible = false;
			addChild(c);
		}
			
		/**
		 * 添加一个地图物品 
		 * @param mapObject 地图物品
		 * @param refreshDepthImmediatly 是否立即刷新深度
		 * @param needrefreshBarriers 是否需要刷新障碍节点
		 * @return 地图物品本身
		 * 
		 */		
		public function addMapObject(mapObject:MapObject, refreshDepthImmediatly:Boolean=false, needrefreshBarriers:Boolean=true):MapObject
		{
			this.objectLayer.addChild(mapObject);
			this._mapObjectManager.addMapObject(mapObject);
			this._depthManager.addItem(mapObject, refreshDepthImmediatly);
			
			if (needrefreshBarriers)
			{
				refreshBarriers();
			}
			
			return mapObject;
		}
		
		/**
		 * 移除一个物品 
		 * @param mapObject 需要从区域中移除的物品
		 * @return 
		 * 
		 */		
		public function removeMapObject(mapObject:MapObject):MapObject
		{
			this._depthManager.removeItem(mapObject);
			this._mapObjectManager.removeMapObject(mapObject);
			
			if (mapObject.parent == this.objectLayer)
			{
				this.objectLayer.removeChild(mapObject);
			}
			
			return mapObject;
		}
		
		/**
		 * 刷新障碍节点，在物品的位置，数量变更后，需要刷新节点 
		 * 
		 */		
		public function refreshBarriers():void
		{
			var items:Array = _mapObjectManager.mapObjects;
			var len:int = items.length;
			var nodes:Array = [];
			
			for (var i:int=0; i<len; ++i)
			{
				nodes = nodes.concat(_mapObjectManager.getObjectPossessNodes(items[i]as MapObject));
			}
			
			_pathMap.clearAllBarriers();
			_pathMap.setBarriers(nodes);
			
			items = null;
			nodes = null;
		}
		
		/**
		 * 创建一个地图上的物品 
		 * @param x 逻辑横轴坐标
		 * @param y 逻辑纵轴坐标
		 * @param objectWidth 物品的宽度
		 * @param objectHeight 物品的高度
		 * @return 创建好的物品
		 * 
		 */		
		public function createMapObject(x:int, y:int, objectWidth:int, objectHeight:int):MapObject
		{
			var m:MapObject = new MapObject(_pathMap.getPathNodeByPosition(x, y), objectWidth, objectHeight);
			return m;
		}
		
		/**
		 * 获取区域的ID 
		 * @return 
		 * 
		 */		
		public function get id():int
		{
			return this._id;
		}
		
		/**
		 * 设置是否采用地板缓存功能，采用此功能可以大大提高渲染效率
		 * @param value
		 * 
		 */		
		public function set floorUseCache(value:Boolean):void
		{
			if (value != this._floorUseCache)
			{
				this._floorUseCache = value;
				
				if (value && this.floorLayer.width > 0)
				{
					_floorBitmap = _floorBitmap || new Bitmap();
					cacheLayerAsBitmap(floorLayer, _floorBitmap);
					bitmapCacheLayer.addChildAt(_floorBitmap, 0);
					drawInteractiveGraphic();
					bitmapCacheLayer.visible = true;
					
					if (floorLayer.parent)
					{
						floorLayer.parent.removeChild(floorLayer);
					}
				}
				else
				{
					if (floorLayer)
					{
						addChildAt(floorLayer, 1);
						bitmapCacheLayer.visible = false;
					}
				}
			}
		}
		
		/**
		 * 用位图缓存某个层，缓存层能够提高运行效率 
		 * @param layer 需要被缓存的层
		 * @param bmp 用于放置位图的对象
		 * 
		 */		
		protected function cacheLayerAsBitmap(layer:Sprite, bmp:Bitmap):void
		{
			if (layer.width > 0)
			{
				var _bitmapData:BitmapData;
				var rect:Rectangle = layer.getRect(layer);
				_bitmapData = new BitmapData(layer.width, layer.height, true, 0);
				var m:Matrix = new Matrix();
				m.translate(-rect.x, -rect.y);
				_bitmapData.draw(layer, m);
				
				bmp.bitmapData = _bitmapData;
				bmp.x = rect.x;
				bmp.y = rect.y;
			}
		}
		
		/**
		 * 绘制鼠标响应区域 
		 * 
		 */		
		protected function drawInteractiveGraphic():void
		{
			if (backgroundLayer)
			{
				backgroundLayer.graphics.beginFill(0xffffff, 0);
				backgroundLayer.graphics.moveTo(0, 0);
				var p:Point = PositionCalculator.getPosition(0, this._pathMap.height);
				backgroundLayer.graphics.lineTo(p.x, p.y);
				p = PositionCalculator.getPosition(_pathMap.width, _pathMap.height);
				backgroundLayer.graphics.lineTo(p.x, p.y);
				p = PositionCalculator.getPosition(_pathMap.width, 0);
				backgroundLayer.graphics.lineTo(p.x, p.y);
				backgroundLayer.graphics.lineTo(0, 0);
				backgroundLayer.graphics.endFill();
			}
		}
		
		/**
		 * 获取当前是否启用了地板缓存功能 
		 * @return 
		 * 
		 */		
		public function get floorUseCache():Boolean
		{
			return this._floorUseCache;
		}
		
		protected function generateLayer():void
		{
			floorLayer = new Sprite();
			bitmapCacheLayer = new Sprite();
			floorItemLayer = new Sprite();
			objectLayer = new Sprite();
			backgroundLayer = new Sprite();
			tipsLayer = new Sprite();
			
			bitmapCacheLayer.mouseChildren = bitmapCacheLayer.mouseEnabled = bitmapCacheLayer.visible = false;
			
			addChild(bitmapCacheLayer);
			addChild(backgroundLayer);
			addChild(floorLayer);
			addChild(floorItemLayer);
			addChild(objectLayer);
			addChild(tipsLayer);
		}
		
		protected function initManager():void
		{
			this._depthManager = new DepthManager(objectLayer, true, mode);
			this._mapObjectManager = new MapObjectManager(objectLayer, this._pathMap);
		}
		
		protected function initListener():void
		{
			objectLayer.addEventListener(MapObjectEvent.POSTION_CHANGE, handleItemPositionChanged);
		}
		
		protected function removeListener():void
		{
			objectLayer.removeEventListener(MapObjectEvent.POSTION_CHANGE, handleItemPositionChanged);
		}
		
		protected function handleItemPositionChanged(e:MapObjectEvent):void
		{
			var item:MapObject = e.target as MapObject;
			
			if (item)
			{
				refreshBarriers();
			}
		}
		
		/**
		 * 生成地板 
		 * @param defaultFloorClass 默认地板的Class
		 * @param floorClasses 地板的类的数据列
		 * 
		 */		
		public function generateFloor(floorClasses:Array, defaultFloorClass:String):void
		{
			FloorGenerator.generateFloor(this, floorClasses, defaultFloorClass);
		}
		
		/**
		 * 移除所有的层 
		 * 
		 */		
		protected function removeAllLayer():void
		{
			if (floorLayer && bitmapCacheLayer && floorItemLayer && objectLayer && backgroundLayer)
			{
				removeLayer(floorLayer);
				removeLayer(bitmapCacheLayer);
				removeLayer(floorItemLayer);
				removeLayer(objectLayer);
				removeLayer(backgroundLayer);
				removeLayer(tipsLayer);
			}
		}
		
		/**
		 * 移除层 
		 * @param layer
		 * 
		 */		
		protected function removeLayer(layer:Sprite):void
		{
			if (layer && layer.parent)
			{
				layer.parent.removeChild(layer);
				
				var c:DisplayObject;
				
				while (layer.numChildren)
				{
					c = layer.getChildAt(0)
					layer.removeChild(c);
				}
			}
		}
		
		/**
		 * 获取逻辑横坐标 
		 * @return 
		 * 
		 */		
		public function get logicalX():int
		{
			return this._nodeX;
		}
		
		/**
		 * 获取逻辑纵坐标 
		 * 
		 */		
		public function get logicalY():int
		{
			return this._nodeY;
		}
		
		/**
		 * 获取区域的面积 
		 * @return 
		 * 
		 */		
		public function get areaSize():int
		{
			return this._pathMap.numPathNodes;
		}
		
		/**
		 * 面积的宽度 
		 * @return 
		 * 
		 */		
		public function get areaWidth():int
		{
			return this._pathMap.width;
		}
		
		/**
		 * 面积的高度 
		 * @return 
		 * 
		 */		
		public function get areaHeight():int
		{
			return this._pathMap.height;
		}
		
		/**
		 * 获取深度值 
		 * @return 
		 * 
		 */		
		public function get zIndex():int
		{
			return this._nodeX + this._nodeY;
		}
		
		/**
		 * 获取地图对象 
		 * @return 
		 * 
		 */		
		public function get pathMap():PathMap
		{
			return this._pathMap;
		}
		
		/**
		 * 获取物品管理器 
		 * @return 
		 * 
		 */		
		public function get mapObjectManager():MapObjectManager
		{
			return this._mapObjectManager;
		}
		
		/**
		 * 强制刷新层级 
		 * 
		 */		
		public function refreshDepth():void
		{
			this._depthManager.refreshDepth();
		}
		
		/**
		 * 销毁对象 
		 * 
		 */		
		public function destroy():void
		{
			removeListener();
			removeAllLayer();
			
			if (this._depthManager)
			{
				this._depthManager.destroy();
			}
			
			if (this._mapObjectManager)
			{
				this._mapObjectManager.destroy();
			}
			
			if (this._pathMap)
			{
				this._pathMap.destroy();
			}
			
			if (_floorBitmap)
			{
				if (_floorBitmap.parent)
				{
					_floorBitmap.parent.removeChild(_floorBitmap);
				}
				
				_floorBitmap = null;
			}
			
			this.objectLayer = null;
			this.floorLayer = null;
			this.floorItemLayer = null;
			this.bitmapCacheLayer = null;
			this._pathMap = null;
		}
	}
}